home *** CD-ROM | disk | FTP | other *** search
/ Dr. Windows 3 / dr win3.zip / dr win3 / PROGRAMR / OLE2BOOK.ZIP / CHAP13.ZIP / PATRON / DOCUMENT.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-19  |  35.9 KB  |  1,578 lines

  1. /*
  2.  * DOCUMENT.CPP
  3.  * Modifications for Chapter 13
  4.  *
  5.  * Implementation of the CPatronDoc derivation of CDocument that
  6.  * manages pages for us.
  7.  *
  8.  * Copyright (c)1993 Microsoft Corporation, All Rights Reserved
  9.  *
  10.  * Kraig Brockschmidt, Software Design Engineer
  11.  * Microsoft Systems Developer Relations
  12.  *
  13.  * Internet  :  kraigb@microsoft.com
  14.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  15.  */
  16.  
  17.  
  18. #include <memory.h>
  19. #include "patron.h"
  20.  
  21.  
  22.  
  23. /*
  24.  * CPatronDoc::CPatronDoc
  25.  * CPatronDoc::~CPatronDoc
  26.  *
  27.  * Constructor Parameters:
  28.  *  hInst           HINSTANCE of the application.
  29.  */
  30.  
  31. CPatronDoc::CPatronDoc(HINSTANCE hInst)
  32.     : CDocument(hInst)
  33.     {
  34.     m_pPG=NULL;
  35.     m_lVer=VERSIONCURRENT;
  36.     m_pIStorage=NULL;
  37.     m_fPrintSetup=TRUE;
  38.     m_pDropTarget=NULL;
  39.  
  40.     m_cfEmbeddedObject   =RegisterClipboardFormat(CF_EMBEDDEDOBJECT);
  41.     m_cfObjectDescriptor =RegisterClipboardFormat(CF_OBJECTDESCRIPTOR);
  42.     m_cfLinkSource       =RegisterClipboardFormat(CF_LINKSOURCE);
  43.     m_cfLinkSrcDescriptor=RegisterClipboardFormat(CF_LINKSRCDESCRIPTOR);
  44.     m_fShowTypes         =FALSE;
  45.  
  46.     //CHAPTER13MOD
  47.     m_cRef               =1L;
  48.     m_fRename            =TRUE;
  49.     m_dwRegROT           =0L;
  50.     m_pIPersistFile      =NULL;
  51.     m_pIOleItemContainer =NULL;
  52.     //End CHAPTER13MOD
  53.  
  54.     return;
  55.     }
  56.  
  57.  
  58. CPatronDoc::~CPatronDoc(void)
  59.     {
  60.     //CHAPTER13MOD
  61.     if (0L!=m_dwRegROT)
  62.         OleStdRevokeAsRunning(&m_dwRegROT);
  63.  
  64.     if (NULL!=m_pIPersistFile)
  65.         delete m_pIPersistFile;
  66.  
  67.     if (NULL!=m_pIOleItemContainer)
  68.         delete m_pIOleItemContainer;
  69.     //End CHAPTER13MOD
  70.  
  71.     if (NULL!=m_pDropTarget)
  72.         {
  73.         RevokeDragDrop(m_hWnd);
  74.         CoLockObjectExternal((LPUNKNOWN)m_pDropTarget, FALSE, TRUE);
  75.         m_pDropTarget->Release();
  76.         }
  77.  
  78.     if (NULL!=m_pPG)
  79.         delete m_pPG;
  80.  
  81.     if (NULL!=m_pIStorage)
  82.         m_pIStorage->Release();
  83.  
  84.     CoFreeUnusedLibraries();
  85.  
  86.     return;
  87.     }
  88.  
  89.  
  90.  
  91. //CHAPTER13MOD
  92.  
  93. /*
  94.  * CPatronDoc::QueryInterface
  95.  * CPatronDoc::AddRef
  96.  * CPatronDoc::Release
  97.  *
  98.  * Purpose:
  99.  *  IUnknown members for CPatronDoc object.
  100.  */
  101.  
  102. STDMETHODIMP CPatronDoc::QueryInterface(REFIID riid, LPLPVOID ppv)
  103.     {
  104.     *ppv=NULL;
  105.  
  106.     /*
  107.      * WARNING:  If you are using multiple inheritance, like I am
  108.      * with CPatronDoc, you'd better be sure to typecast "this" into
  109.      * an IUnknown to point to the right function table.  In developing
  110.      * this I forgot, and the AddRef call below ended up in the
  111.      * destructor!  Wrong function table!
  112.      */
  113.  
  114.     if (IsEqualIID(riid, IID_IUnknown))
  115.         *ppv=(LPVOID)(LPUNKNOWN)this;
  116.  
  117.     if (IsEqualIID(riid, IID_IOleItemContainer)
  118.         || IsEqualIID(riid, IID_IOleContainer)
  119.         || IsEqualIID(riid, IID_IParseDisplayName))
  120.         *ppv=(LPVOID)m_pIOleItemContainer;
  121.  
  122.     if (IsEqualIID(riid, IID_IPersistFile) || IsEqualIID(riid, IID_IPersist))
  123.         *ppv=(LPVOID)m_pIPersistFile;
  124.  
  125.     if (NULL!=*ppv)
  126.         {
  127.         ((LPUNKNOWN)*ppv)->AddRef();
  128.         return NOERROR;
  129.         }
  130.  
  131.     return ResultFromScode(E_NOINTERFACE);
  132.     }
  133.  
  134.  
  135. STDMETHODIMP_(ULONG) CPatronDoc::AddRef(void)
  136.     {
  137.     return ++m_cRef;
  138.     }
  139.  
  140. STDMETHODIMP_(ULONG) CPatronDoc::Release(void)
  141.     {
  142.     ULONG           cRefT;
  143.  
  144.     cRefT=--m_cRef;
  145.  
  146.     if (0L==m_cRef)
  147.         {
  148.         /*
  149.          * Telling ourselves to WM_CLOSE will inform the frame that will
  150.          * ask the client to CloseDocument which will delete us when
  151.          * appropriate.  We then call ObjectDestroyed in our destructor
  152.          * to initiate full shutdown.
  153.          */
  154.         PostMessage(m_hWnd, WM_CLOSE, 0, 0);
  155.         }
  156.  
  157.     return cRefT;
  158.     }
  159. //End CHAPTER13MOD
  160.  
  161.  
  162.  
  163. /*
  164.  * CPatronDoc::FInit
  165.  *
  166.  * Purpose:
  167.  *  Initializes an already created document window.  The client actually
  168.  *  creates the window for us, then passes that here for further
  169.  *  initialization.
  170.  *
  171.  * Parameters:
  172.  *  pDI             LPDOCUMENTINIT containing initialization parameters.
  173.  *
  174.  * Return Value:
  175.  *  BOOL            TRUE if the function succeeded, FALSE otherwise.
  176.  */
  177.  
  178. BOOL CPatronDoc::FInit(LPDOCUMENTINIT pDI)
  179.     {
  180.     //Change the stringtable range to our customization.
  181.     pDI->idsMin=IDS_DOCUMENTMIN;
  182.     pDI->idsMax=IDS_DOCUMENTMAX;
  183.  
  184.     //Do default initialization
  185.     if (!CDocument::FInit(pDI))
  186.         return FALSE;
  187.  
  188.     //Pages are created when we get a ::ULoad later.
  189.  
  190.     //CHAPTER13MOD
  191.     //Instantiate our interfaces
  192.     m_pIPersistFile=new CImpIPersistFile(this, (LPUNKNOWN)this);
  193.  
  194.     if (NULL==m_pIPersistFile)
  195.         return FALSE;
  196.  
  197.     m_pIOleItemContainer=new CImpIOleItemContainer((LPVOID)this
  198.         , (LPUNKNOWN)this, TRUE);
  199.  
  200.     if (NULL==m_pIOleItemContainer)
  201.         return FALSE;
  202.  
  203.     //End CHAPTER13MOD
  204.  
  205.     return TRUE;
  206.     }
  207.  
  208.  
  209.  
  210.  
  211.  
  212.  
  213. /*
  214.  * CPatronDoc::FMessageHook
  215.  *
  216.  * Purpose:
  217.  *  Processes WM_SIZE for the document so we can resize the Pages window.
  218.  *
  219.  * Parameters:
  220.  *  <WndProc Parameters>
  221.  *  pLRes           LRESULT FAR * in which to store the return value
  222.  *                  for the message.
  223.  *
  224.  * Return Value:
  225.  *  BOOL            TRUE to prevent further processing, FALSE otherwise.
  226.  */
  227.  
  228. BOOL CPatronDoc::FMessageHook(HWND hWnd, UINT iMsg, WPARAM wParam
  229.     , LPARAM lParam, LRESULT FAR *pLRes)
  230.     {
  231.     UINT        dx, dy;
  232.     RECT        rc;
  233.  
  234.     if (WM_SIZE==iMsg && NULL!=m_pPG)
  235.         {
  236.         dx=LOWORD(lParam);
  237.         dy=HIWORD(lParam);
  238.  
  239.         //Resize the Pages window to fit the new client area of the document
  240.         GetClientRect(hWnd, &rc);
  241.         m_pPG->RectSet(&rc, FALSE);
  242.         }
  243.  
  244.     /*
  245.      * We return FALSE even on WM_SIZE so we can let the default procedure
  246.      * handle maximized MDI child windows appropriately.
  247.      */
  248.     return FALSE;
  249.     }
  250.  
  251.  
  252.  
  253.  
  254.  
  255.  
  256.  
  257.  
  258. /*
  259.  * CPatronDoc::Clear
  260.  *
  261.  * Purpose:
  262.  *  Sets all contents in the document back to defaults with no filename.
  263.  *
  264.  * Paramters:
  265.  *  None
  266.  *
  267.  * Return Value:
  268.  *  None
  269.  */
  270.  
  271. void CPatronDoc::Clear(void)
  272.     {
  273.     //Completely reset the pages
  274.     if (NULL!=m_pPG)
  275.         m_pPG->FIStorageSet(NULL, FALSE, FALSE);
  276.  
  277.     CDocument::Clear();
  278.     m_lVer=VERSIONCURRENT;
  279.     return;
  280.     }
  281.  
  282.  
  283.  
  284.  
  285. /*
  286.  * CPatronDoc::FDirtyGet
  287.  *
  288.  * Purpose:
  289.  *  Returns the current dirty status of the document.
  290.  *
  291.  * Parameters:
  292.  *  None
  293.  *
  294.  * Return Value:
  295.  *  BOOL            TRUE if the file is clean, FALSE otherwise.
  296.  */
  297.  
  298. BOOL CPatronDoc::FDirtyGet()
  299.     {
  300.     BOOL    fPageDirty=FALSE;
  301.  
  302.     if (NULL!=m_pPG)
  303.         fPageDirty=m_pPG->FIsDirty();
  304.  
  305.     return m_fDirty | fPageDirty;
  306.     }
  307.  
  308.  
  309.  
  310.  
  311.  
  312. /*
  313.  * CPatronDoc::Delete
  314.  *
  315.  * Purpose:
  316.  *  Removed the current object from the document.
  317.  *
  318.  * Paramters:
  319.  *  None
  320.  *
  321.  * Return Value:
  322.  *  None
  323.  */
  324.  
  325. void CPatronDoc::Delete(void)
  326.     {
  327.     if (NULL!=m_pPG)
  328.         m_pPG->TenantDestroy();
  329.  
  330.     CoFreeUnusedLibraries();
  331.     return;
  332.     }
  333.  
  334.  
  335.  
  336. /*
  337.  * CPatronDoc::FQueryPrinterSetup
  338.  *
  339.  * Purpose:
  340.  *  Returns whether or not the Printer Setup menu item can be
  341.  *  enabled.  Once you create a tenant in any page, Printer Setup
  342.  *  is voided simply to keep this sample simple, that is, we don't
  343.  *  have to worry about reorganizing potentially large amounts
  344.  *  of layout after we start plopping down objects.
  345.  *
  346.  * Parameters:
  347.  *  None
  348.  *
  349.  * Return Value:
  350.  *  BOOL            TRUE to enable the menu, FALSE otherwise.
  351.  */
  352.  
  353. BOOL CPatronDoc::FQueryPrinterSetup(void)
  354.     {
  355.     return m_fPrintSetup;
  356.     }
  357.  
  358.  
  359.  
  360.  
  361.  
  362. /*
  363.  * CPatronDoc::FQueryObjectSelected
  364.  *
  365.  * Purpose:
  366.  *  Returns whether or not there is an object selected in this
  367.  *  document for Cut, Copy, Delete functions.
  368.  *
  369.  * Parameters:
  370.  *  hMenu           HMENU of the Edit menu.
  371.  *
  372.  * Return Value:
  373.  *  BOOL            TRUE if we have an object, FALSE otherwise.
  374.  */
  375.  
  376. BOOL CPatronDoc::FQueryObjectSelected(HMENU hMenu)
  377.     {
  378.     if (NULL!=m_pPG)
  379.         return m_pPG->FQueryObjectSelected(hMenu);
  380.  
  381.     return FALSE;
  382.     }
  383.  
  384.  
  385.  
  386.  
  387.  
  388. /*
  389.  * CPatronDoc::ULoad
  390.  *
  391.  * Purpose:
  392.  *  Loads a given document without any user interface overwriting the
  393.  *  previous contents of the editor.
  394.  *
  395.  * Parameters:
  396.  *  fChangeFile     BOOL indicating if we're to update the window title
  397.  *                  and the filename from using this file.
  398.  *  pszFile         LPSTR to the filename to load.  Could be NULL for
  399.  *                  an untitled document.
  400.  *
  401.  * Return Value:
  402.  *  UINT            An error value from DOCERR_*
  403.  */
  404.  
  405.  
  406. UINT CPatronDoc::ULoad(BOOL fChangeFile, LPSTR pszFile)
  407.     {
  408.     RECT        rc;
  409.     LPSTORAGE   pIStorage;
  410.     HRESULT     hr;
  411.     CLSID       clsID;
  412.     DWORD       dwMode=STGM_TRANSACTED | STGM_READWRITE | STGM_SHARE_EXCLUSIVE;
  413.  
  414.     if (NULL==pszFile)
  415.         {
  416.         //Create a new temp file.
  417.         hr=StgCreateDocfile(NULL, dwMode | STGM_CREATE | STGM_DELETEONRELEASE
  418.             , 0, &pIStorage);
  419.  
  420.         //Mark this as one of our class since we check with ReadClassStg below.
  421.         if (SUCCEEDED(hr))
  422.             WriteClassStg(pIStorage, CLSID_PatronPages);
  423.         }
  424.     else
  425.         {
  426.         hr=StgOpenStorage(pszFile, NULL, dwMode, NULL, 0, &pIStorage);
  427.         }
  428.  
  429.     if (FAILED(hr))
  430.         return DOCERR_COULDNOTOPEN;
  431.  
  432.     //Check if this is our type of file and exit if not.
  433.     hr=ReadClassStg(pIStorage, &clsID);
  434.  
  435.     if (FAILED(hr) || !IsEqualCLSID(clsID, CLSID_PatronPages))
  436.         {
  437.         pIStorage->Release();
  438.         return DOCERR_READFAILURE;
  439.         }
  440.  
  441.     //Attempt to create our contained Pages window.
  442.     m_pPG=new CPages(m_hInst, m_cf);
  443.     GetClientRect(m_hWnd, &rc);
  444.  
  445.     if (!m_pPG->FInit(m_hWnd, &rc, WS_CHILD | WS_VISIBLE, ID_PAGES, NULL))
  446.         {
  447.         pIStorage->Release();
  448.         return DOCERR_READFAILURE;
  449.         }
  450.  
  451.     if (!m_pPG->FIStorageSet(pIStorage, FALSE, (BOOL)(NULL==pszFile)))
  452.         {
  453.         pIStorage->Release();
  454.         return DOCERR_READFAILURE;
  455.         }
  456.  
  457.     //Open the window up for drag-drop
  458.     m_pDropTarget=new CDropTarget(this);
  459.  
  460.     if (NULL!=m_pDropTarget)
  461.         {
  462.         m_pDropTarget->AddRef();
  463.         RegisterDragDrop(m_hWnd, (LPDROPTARGET)m_pDropTarget);
  464.         CoLockObjectExternal((LPUNKNOWN)m_pDropTarget, TRUE, FALSE);
  465.         }
  466.  
  467.     m_pIStorage=pIStorage;
  468.     Rename(pszFile);
  469.  
  470.     //Do initial setup if this is a new file, otherwise Pages handles things.
  471.     if (NULL==pszFile)
  472.         {
  473.         //Go initialize the Pages for the default printer.
  474.         if (!PrinterSetup(NULL, TRUE))
  475.             return DOCERR_COULDNOTOPEN;
  476.  
  477.         //Go create an initial page.
  478.         m_pPG->PageInsert(0);
  479.         }
  480.     else
  481.         m_fPrintSetup=FALSE;    //Can't change an already saved configuration
  482.  
  483.     FDirtySet(FALSE);
  484.     return DOCERR_NONE;
  485.     }
  486.  
  487.  
  488.  
  489.  
  490.  
  491.  
  492.  
  493. /*
  494.  * CPatronDoc::USave
  495.  *
  496.  * Purpose:
  497.  *  Writes the file to a known filename, requiring that the user has
  498.  *  previously used FileOpen or FileSaveAs in order to have a filename.
  499.  *
  500.  * Parameters:
  501.  *  uType           UINT indicating the type of file the user requested
  502.  *                  to save in the File Save As dialog.
  503.  *  pszFile         LPSTR under which to save.  If NULL, use the current name.
  504.  *
  505.  * Return Value:
  506.  *  UINT            An error value from DOCERR_*
  507.  */
  508.  
  509. UINT CPatronDoc::USave(UINT uType, LPSTR pszFile)
  510.     {
  511.     HRESULT     hr;
  512.     LPSTORAGE   pIStorage;
  513.  
  514.     //Save or Save As with the same file is just a commit.
  515.     if (NULL==pszFile || (NULL!=pszFile && 0==lstrcmpi(pszFile, m_szFile)))
  516.         {
  517.         WriteFmtUserTypeStg(m_pIStorage, m_cf, PSZ(IDS_CLIPBOARDFORMAT));
  518.  
  519.         //Insure pages are up to date.
  520.         m_pPG->FIStorageUpdate(FALSE);
  521.  
  522.         //Commit everyting
  523.         m_pIStorage->Commit(STGC_ONLYIFCURRENT);
  524.  
  525.         FDirtySet(FALSE);
  526.         return DOCERR_NONE;
  527.         }
  528.  
  529.     /*
  530.      * When we're given a name, open the storage, creating it new if
  531.      * it does not exist or overwriting the old one.  Then ::CopyTo
  532.      * from the current to the new, ::Commit the new, then ::Release
  533.      * the old.
  534.      */
  535.  
  536.     hr=StgCreateDocfile(pszFile, STGM_TRANSACTED | STGM_READWRITE
  537.         | STGM_CREATE | STGM_SHARE_EXCLUSIVE, 0, &pIStorage);
  538.  
  539.     if (FAILED(hr))
  540.         return DOCERR_COULDNOTOPEN;
  541.  
  542.     WriteClassStg(pIStorage, CLSID_PatronPages);
  543.     WriteFmtUserTypeStg(pIStorage, m_cf, PSZ(IDS_CLIPBOARDFORMAT));
  544.  
  545.     //Insure all pages are up-to-date.
  546.     m_pPG->FIStorageUpdate(TRUE);
  547.  
  548.     //This also copies the CLSID we stuff in here on file creation.
  549.     hr=m_pIStorage->CopyTo(NULL, NULL, NULL, pIStorage);
  550.  
  551.     if (FAILED(hr))
  552.         {
  553.         pIStorage->Release();
  554.         return DOCERR_WRITEFAILURE;
  555.         }
  556.  
  557.     pIStorage->Commit(STGC_ONLYIFCURRENT);
  558.  
  559.     /*
  560.      * Revert changes on the original storage.  If this was a temp file,
  561.      * it's deleted since we used STGM_DELETEONRELEASE.
  562.      */
  563.     m_pIStorage->Release();
  564.  
  565.     //Make this new storage current
  566.     m_pIStorage=pIStorage;
  567.     m_pPG->FIStorageSet(pIStorage, TRUE, FALSE);
  568.  
  569.     FDirtySet(FALSE);
  570.  
  571.     //CHAPTER13MOD
  572.     if (m_fRename)
  573.         Rename(pszFile);    //Update caption bar.
  574.     //End CHAPTER13MOD
  575.  
  576.     return DOCERR_NONE;
  577.     }
  578.  
  579.  
  580.  
  581.  
  582.  
  583.  
  584.  
  585.  
  586. /*
  587.  * CPatronDoc::FClip
  588.  *
  589.  * Purpose:
  590.  *  Places a private format, a metafile, and a bitmap of the display
  591.  *  on the clipboard, optionally implementing Cut by deleting the
  592.  *  data in the current window after rendering.
  593.  *
  594.  * Parameters:
  595.  *  hWndFrame       HWND of the main window.
  596.  *  fCut            BOOL indicating cut (TRUE) or copy (FALSE).
  597.  *
  598.  * Return Value:
  599.  *  BOOL            TRUE if successful, FALSE otherwise.
  600.  */
  601.  
  602. BOOL CPatronDoc::FClip(HWND hWndFrame, BOOL fCut)
  603.     {
  604.     if (NULL==m_pPG)
  605.         return FALSE;
  606.  
  607.     return m_pPG->TenantClip(fCut);
  608.     }
  609.  
  610.  
  611.  
  612.  
  613.  
  614. /*
  615.  * CPatronDoc::FPaste
  616.  *
  617.  * Purpose:
  618.  *  Retrieves the private data format from the clipboard and sets it
  619.  *  to the current figure in the editor window.
  620.  *
  621.  *  Note that if this function is called, then the clipboard format
  622.  *  is available because the Paste menu item is only enabled if the
  623.  *  format is present.
  624.  *
  625.  * Parameters:
  626.  *  hWndFrame       HWND of the main window.
  627.  *
  628.  * Return Value:
  629.  *  BOOL            TRUE if successful, FALSE otherwise.
  630.  */
  631.  
  632. BOOL CPatronDoc::FPaste(HWND hWndFrame)
  633.     {
  634.     LPDATAOBJECT    pIDataObject;
  635.     BOOL            fRet=FALSE;
  636.     FORMATETC       fe;
  637.     TENANTTYPE      tType;
  638.  
  639.     if (NULL==m_pPG)
  640.         return FALSE;
  641.  
  642.     if (FAILED(OleGetClipboard(&pIDataObject)))
  643.         return FALSE;
  644.  
  645.     //Go get the type and format we *can* paste, then actually paste it.
  646.     if (FQueryPasteFromData(pIDataObject, &fe, &tType))
  647.         fRet=FPasteFromData(pIDataObject, &fe, tType, NULL, 0L, TRUE);
  648.  
  649.     pIDataObject->Release();
  650.     return fRet;
  651.     }
  652.  
  653.  
  654.  
  655.  
  656. /*
  657.  * CPatronDoc::FQueryPaste
  658.  *
  659.  * Purpose:
  660.  *  Determines if we can paste data from the clipboard.
  661.  *
  662.  * Parameters:
  663.  *  None
  664.  *
  665.  * Return Value:
  666.  *  BOOL            TRUE if data is available, FALSE otherwise.
  667.  */
  668.  
  669. BOOL CPatronDoc::FQueryPaste(void)
  670.     {
  671.     LPDATAOBJECT    pIDataObject;
  672.     BOOL            fRet;
  673.  
  674.     if (FAILED(OleGetClipboard(&pIDataObject)))
  675.         return FALSE;
  676.  
  677.     fRet=FQueryPasteFromData(pIDataObject, NULL, NULL);
  678.     fRet |= FQueryPasteLinkFromData(pIDataObject, NULL, NULL);
  679.  
  680.     pIDataObject->Release();
  681.     return fRet;
  682.     }
  683.  
  684.  
  685.  
  686.  
  687.  
  688.  
  689. /*
  690.  * CPatronDoc::FPasteSpecial
  691.  *
  692.  * Purpose:
  693.  *  Retrieves a specific data format from the clipboard and sends it to
  694.  *  the editor window appropriately.
  695.  *
  696.  *  Note that if this function is called, then the appropriate format
  697.  *  is available because the Paste menu item is only enabled if the
  698.  *  format is present.
  699.  *
  700.  * Parameters:
  701.  *  hWndFrame       HWND of the main window
  702.  *
  703.  * Return Value:
  704.  *  BOOL            TRUE if successful, FALSE otherwise.
  705.  */
  706.  
  707. BOOL CPatronDoc::FPasteSpecial(HWND hWndFrame)
  708.     {
  709.     OLEUIPASTESPECIAL   ps;
  710.     OLEUIPASTEENTRY     rgPaste[6];
  711.     UINT                rgcf[1];        //For ps.m_arrLinkTypes
  712.     DWORD               dwData=0;
  713.     UINT                uTemp;
  714.     BOOL                fRet=FALSE;
  715.  
  716.     if (NULL==m_pPG)
  717.         return FALSE;
  718.  
  719.     _fmemset(&ps, 0, sizeof(ps));
  720.  
  721.     if (FAILED(OleGetClipboard(&ps.lpSrcDataObj)))
  722.         return FALSE;
  723.  
  724.     ps.cbStruct=sizeof(ps);
  725.     ps.hWndOwner=hWndFrame;
  726.  
  727.     ps.dwFlags=PSF_SELECTPASTE;
  728.     ps.arrPasteEntries=rgPaste;
  729.  
  730.     //Set up Paste Special descriptor arrays.
  731.     SETDefFormatEtc(rgPaste[0].fmtetc, m_cf, TYMED_HGLOBAL);
  732.     rgPaste[0].lpstrFormatName=PSZ(IDS_CLIPBOARDFORMAT);
  733.     rgPaste[0].lpstrResultText=PSZ(IDS_PASTEASPATRON);
  734.     rgPaste[0].dwFlags=OLEUIPASTE_PASTEONLY;
  735.  
  736.     //Embedded objects can be iconic displays if the user wants.
  737.     SETDefFormatEtc(rgPaste[1].fmtetc, m_cfEmbeddedObject, TYMED_ISTORAGE);
  738.     rgPaste[1].lpstrFormatName="%s Object";
  739.     rgPaste[1].lpstrResultText="%s Object";
  740.  
  741.     /*
  742.      * CAUTION:  Use OLEUI_PASTE with embedded objects or else
  743.      * this item will not show up in the dialog.  I learned this the
  744.      * hard way (that is, after about 6 hours of pulling hair!).
  745.      */
  746.     rgPaste[1].dwFlags=OLEUIPASTE_PASTE | OLEUIPASTE_ENABLEICON;
  747.  
  748.  
  749.     SETDefFormatEtc(rgPaste[2].fmtetc, CF_METAFILEPICT, TYMED_MFPICT);
  750.     rgPaste[2].lpstrFormatName=PSZ(IDS_PASTEMETAFILE);
  751.     rgPaste[2].lpstrResultText=PSZ(IDS_PASTEASMETAFILE);
  752.     rgPaste[2].dwFlags=OLEUIPASTE_PASTEONLY;
  753.  
  754.     SETDefFormatEtc(rgPaste[3].fmtetc, CF_DIB, TYMED_HGLOBAL);
  755.     rgPaste[3].lpstrFormatName=PSZ(IDS_PASTEDIB);
  756.     rgPaste[3].lpstrResultText=PSZ(IDS_PASTEASDIB);
  757.     rgPaste[3].dwFlags=OLEUIPASTE_PASTEONLY;
  758.  
  759.     SETDefFormatEtc(rgPaste[4].fmtetc, CF_BITMAP, TYMED_GDI);
  760.     rgPaste[4].lpstrFormatName=PSZ(IDS_PASTEBITMAP);
  761.     rgPaste[4].lpstrResultText=PSZ(IDS_PASTEASBITMAP);
  762.     rgPaste[4].dwFlags=OLEUIPASTE_PASTEONLY;
  763.  
  764.     SETDefFormatEtc(rgPaste[5].fmtetc, m_cfLinkSource, TYMED_ISTREAM);
  765.     rgPaste[5].lpstrFormatName=PSZ(IDS_PASTELINK);
  766.     rgPaste[5].lpstrResultText=PSZ(IDS_PASTEASLINK);
  767.     rgPaste[5].dwFlags=OLEUIPASTE_LINKTYPE1 | OLEUIPASTE_ENABLEICON;
  768.  
  769.     //Types we can Paste Link from the clipboard.
  770.     rgcf[0]=m_cfLinkSource;
  771.     ps.arrLinkTypes=rgcf;
  772.     ps.cLinkTypes=1;
  773.  
  774.     ps.cPasteEntries=6;
  775.  
  776.     uTemp=OleUIPasteSpecial(&ps);
  777.  
  778.     if (OLEUI_OK==uTemp)
  779.         {
  780.         UINT        i=ps.nSelectedIndex;
  781.         TENANTTYPE  tType;
  782.  
  783.         if (ps.fLink)
  784.             tType=TENANTTYPE_LINKEDOBJECTFROMDATA;
  785.         else
  786.             {
  787.             if (1==ps.nSelectedIndex)
  788.                 tType=TENANTTYPE_EMBEDDEDOBJECTFROMDATA;
  789.             else
  790.                 tType=TENANTTYPE_STATIC;
  791.             }
  792.  
  793.         //Handle iconic aspects...from links as well
  794.         if ((1==i || ps.fLink) && (PSF_CHECKDISPLAYASICON & ps.dwFlags)
  795.             && NULL!=ps.hMetaPict)
  796.             {
  797.             rgPaste[i].fmtetc.dwAspect=DVASPECT_ICON;
  798.             dwData=(DWORD)(UINT)ps.hMetaPict;
  799.             }
  800.  
  801.         fRet=FPasteFromData(ps.lpSrcDataObj, &rgPaste[i].fmtetc
  802.             , tType, NULL, dwData, FALSE);
  803.  
  804.         //Always free this regardless of what we do with it.
  805.         if (NULL!=ps.hMetaPict)
  806.             OleUIMetafilePictIconFree(ps.hMetaPict);
  807.         }
  808.  
  809.     ps.lpSrcDataObj->Release();
  810.     return fRet;
  811.     }
  812.  
  813.  
  814.  
  815.  
  816. /*
  817.  * CPatronDoc::FQueryPasteFromData
  818.  * (Protected)
  819.  *
  820.  * Purpose:
  821.  *  Determines if we can paste data from a data object.
  822.  *
  823.  * Parameters:
  824.  *  pIDataObject    LPDATAOBJECT from which we might want to paste.
  825.  *  pFE             LPFORMATETC in which to return the first format
  826.  *                  we can use.  Ignored if NULL.
  827.  *  ptType          LPTENANTTYPE in which to store the type of object we
  828.  *                  can paste.  Ignored if NULL.
  829.  *
  830.  * Return Value:
  831.  *  BOOL            TRUE if data is available, FALSE otherwise.
  832.  */
  833.  
  834. BOOL CPatronDoc::FQueryPasteFromData(LPDATAOBJECT pIDataObject
  835.     , LPFORMATETC pFE, LPTENANTTYPE ptType)
  836.     {
  837.     FORMATETC       fe;
  838.     HRESULT         hr, hr2;
  839.  
  840.     //Default is static
  841.     if (NULL!=(LPVOID)ptType)
  842.         *ptType=TENANTTYPE_STATIC;
  843.  
  844.     //Any of our specific data here?
  845.     SETDefFormatEtc(fe, m_cf, TYMED_HGLOBAL);
  846.     hr=pIDataObject->QueryGetData(&fe);
  847.  
  848.     //If embedded object data is available, set the appropriate type
  849.     hr2=OleQueryCreateFromData(pIDataObject);
  850.  
  851.     if (NOERROR==hr2)
  852.         {
  853.         if (NULL!=pFE)
  854.             {
  855.             /*
  856.              * Default to content.  FPaste will use CF_OBJECTDESCRIPTOR
  857.              * to figure the actual aspect.
  858.              */
  859.             SETDefFormatEtc(*pFE, m_cfEmbeddedObject, TYMED_ISTORAGE);
  860.             }
  861.  
  862.         if (NULL!=(LPVOID)ptType)
  863.             *ptType=TENANTTYPE_EMBEDDEDOBJECTFROMDATA;
  864.  
  865.         /*
  866.          * Return now if PatronObject wasn't available, otherwise
  867.          * break out so that pFE gets PatronObject format.
  868.          */
  869.         if (NOERROR!=hr)
  870.             return TRUE;
  871.         }
  872.  
  873.  
  874.     if (NOERROR!=hr && NOERROR!=hr2)
  875.         {
  876.         //Try metafile, DIB, then bitmap, setting fe each time for TenantCreate
  877.         SETDefFormatEtc(fe, CF_METAFILEPICT, TYMED_MFPICT);
  878.         hr=pIDataObject->QueryGetData(&fe);
  879.  
  880.         if (NOERROR!=hr)
  881.             {
  882.             SETDefFormatEtc(fe, CF_DIB, TYMED_HGLOBAL);
  883.             hr=pIDataObject->QueryGetData(&fe);
  884.  
  885.             if (NOERROR!=hr)
  886.                 {
  887.                 SETDefFormatEtc(fe, CF_BITMAP, TYMED_GDI);
  888.                 hr=pIDataObject->QueryGetData(&fe);
  889.                 }
  890.             }
  891.         }
  892.  
  893.     if (NOERROR==hr && NULL!=pFE)
  894.         *pFE=fe;
  895.  
  896.     return (NOERROR==hr);
  897.     }
  898.  
  899.  
  900.  
  901. /*
  902.  * CPatronDoc::FQueryPasteLinkFromData
  903.  * (Protected)
  904.  *
  905.  * Purpose:
  906.  *  Determines if we can paste link from a data object.
  907.  *
  908.  * Parameters:
  909.  *  pIDataObject    LPDATAOBJECT from which we might want to paste.
  910.  *  pFE             LPFORMATETC in which to return the first format
  911.  *                  we can use.  Ignored if NULL.
  912.  *  ptType          LPTENANTTYPE in which to store the type of object we
  913.  *                  can paste.  Ignored if NULL.
  914.  *
  915.  * Return Value:
  916.  *  BOOL            TRUE if data is available, FALSE otherwise.
  917.  */
  918.  
  919. BOOL CPatronDoc::FQueryPasteLinkFromData(LPDATAOBJECT pIDataObject
  920.     , LPFORMATETC pFE, LPTENANTTYPE ptType)
  921.     {
  922.     HRESULT         hr;
  923.  
  924.     if (NULL==pIDataObject)
  925.         return FALSE;
  926.  
  927.     hr=OleQueryLinkFromData(pIDataObject);
  928.  
  929.     if (NOERROR!=hr)
  930.         return FALSE;
  931.  
  932.     if (NULL!=pFE)
  933.         SETDefFormatEtc(*pFE, m_cfLinkSource, TYMED_ISTREAM);
  934.  
  935.     if (NULL!=(LPVOID)ptType)
  936.         *ptType=TENANTTYPE_LINKEDOBJECTFROMDATA;
  937.  
  938.     return TRUE;
  939.     }
  940.  
  941.  
  942.  
  943.  
  944.  
  945.  
  946. /*
  947.  * CPatronDoc::FPasteFromData
  948.  * (Protected)
  949.  *
  950.  * Purpose:
  951.  *  Retrieves the private data format from a data object and sets it
  952.  *  to the current figure in the editor window.
  953.  *
  954.  * Parameters:
  955.  *  pIDataObject    LPDATAOBJECT from which to paste.
  956.  *  pFE             LPFORMATETC to use in the paste. Cannot be NULL.
  957.  *  tType           TENANTTYPE to paste.
  958.  *  ppo             LPPATRONOBJECT containing placement data.
  959.  *  dwData          DWORD extra data sensitive to tType
  960.  *  fUseObjDesc     BOOL indicating if we're to use CF_OBJECTDESCRIPTOR
  961.  *                  format for determining the aspect of the object if
  962.  *                  the format is available.
  963.  *
  964.  * Return Value:
  965.  *  BOOL            TRUE if successful, FALSE otherwise.
  966.  */
  967.  
  968. BOOL CPatronDoc::FPasteFromData(LPDATAOBJECT pIDataObject, LPFORMATETC pFE
  969.     , TENANTTYPE tType, LPPATRONOBJECT ppo, DWORD dwData, BOOL fUseObjDesc)
  970.     {
  971.     BOOL                fRet;
  972.     HRESULT             hr;
  973.     PATRONOBJECT        po;
  974.     STGMEDIUM           stm;
  975.     LPOBJECTDESCRIPTOR  pOD;
  976.     FORMATETC           fe;
  977.     BOOL                fRelease=FALSE;
  978.  
  979.     if (NULL==pFE)
  980.         return FALSE;
  981.  
  982.     //If we're not given any placement data, see if we can retrieve it
  983.     if (pFE->cfFormat==m_cf && NULL==ppo)
  984.         {
  985.         hr=pIDataObject->GetData(pFE, &stm);
  986.  
  987.         if (SUCCEEDED(hr))
  988.             {
  989.             ppo=(LPPATRONOBJECT)GlobalLock(stm.hGlobal);
  990.  
  991.             po=*ppo;
  992.             ppo=&po;
  993.  
  994.             //If there's an object here, make sure the type is right.
  995.             if (ppo->fe.cfFormat==m_cfEmbeddedObject)
  996.                 tType=TENANTTYPE_EMBEDDEDOBJECTFROMDATA;
  997.  
  998.             if (ppo->fe.cfFormat==m_cfLinkSource)
  999.                 tType=TENANTTYPE_LINKEDOBJECTFROMDATA;
  1000.  
  1001.             GlobalUnlock(stm.hGlobal);
  1002.             ReleaseStgMedium(&stm);
  1003.             }
  1004.         }
  1005.  
  1006.     /*
  1007.      * If we're told to look at CF_OBJECTDESCRIPTOR, then try to get the
  1008.      * data and copy the aspect out of it.  We're not interested in any
  1009.      * other part of it, however.  If this fails, also, try
  1010.      * CF_LINKSRCDESCRIPTOR.
  1011.      */
  1012.     if (fUseObjDesc)
  1013.         {
  1014.         SETDefFormatEtc(fe, m_cfObjectDescriptor, TYMED_HGLOBAL);
  1015.  
  1016.         hr=pIDataObject->GetData(&fe, &stm);
  1017.  
  1018.         if (FAILED(hr))
  1019.             {
  1020.             SETDefFormatEtc(fe, m_cfLinkSrcDescriptor, TYMED_HGLOBAL);
  1021.             hr=pIDataObject->GetData(&fe, &stm);
  1022.             }
  1023.  
  1024.         if (SUCCEEDED(hr))
  1025.             {
  1026.             pOD=(LPOBJECTDESCRIPTOR)GlobalLock(stm.hGlobal);
  1027.             pFE->dwAspect=pOD->dwDrawAspect;
  1028.  
  1029.             if (NULL!=ppo)
  1030.                 ppo->fe.dwAspect=pFE->dwAspect;
  1031.  
  1032.             GlobalUnlock(stm.hGlobal);
  1033.             ReleaseStgMedium(&stm);
  1034.  
  1035.             /*
  1036.              * Furthermore, if pFE->dwAspect is DVASPECT_ICON, get the
  1037.              * metafile which will always be the icon representation.
  1038.              */
  1039.             SETFormatEtc(fe, CF_METAFILEPICT, DVASPECT_ICON, NULL
  1040.                 , TYMED_MFPICT, -1);
  1041.  
  1042.             if (SUCCEEDED(pIDataObject->GetData(&fe, &stm)))
  1043.                 {
  1044.                 dwData=(DWORD)(UINT)stm.hGlobal;
  1045.                 fRelease=TRUE;
  1046.                 }
  1047.             }
  1048.         }
  1049.  
  1050.     fRet=m_pPG->TenantCreate(tType, (LPVOID)pIDataObject, pFE, ppo, dwData);
  1051.  
  1052.     //Release the stm from the last GetData
  1053.     if (fRelease)
  1054.         ReleaseStgMedium(&stm);
  1055.  
  1056.     if (fRet)
  1057.         {
  1058.         //Disable Printer Setup once we've created a tenant.
  1059.         m_fPrintSetup=FALSE;
  1060.         FDirtySet(TRUE);
  1061.         }
  1062.  
  1063.     return fRet;
  1064.     }
  1065.  
  1066.  
  1067.  
  1068. /*
  1069.  * CPatronDoc::FQueryEnableEditLinks
  1070.  *
  1071.  * Purpose:
  1072.  *  Determines whether or not the Edit Links menu item should be
  1073.  *  enabled on the frame window menu.
  1074.  *
  1075.  * Parameters:
  1076.  *  None
  1077.  *
  1078.  * Return Value:
  1079.  *  BOOL            TRUE to enable the item, FALSE otherwise.
  1080.  */
  1081.  
  1082. BOOL CPatronDoc::FQueryEnableEditLinks(void)
  1083.     {
  1084.     return m_pPG->FQueryLinksInPage();
  1085.     }
  1086.  
  1087.  
  1088.  
  1089.  
  1090.  
  1091. /*
  1092.  * CPatronDoc::FEditLinks
  1093.  *
  1094.  * Purpose:
  1095.  *  Invokes the links dialog in which the end-user can manipulate all
  1096.  *  the links in the current page.
  1097.  *
  1098.  * Parameters:
  1099.  *  hWndFrame       HWND of the frame window to use as the dialog parent.
  1100.  *
  1101.  * Return Value:
  1102.  *  BOOL            TRUE if the function was successful, FALSE otherwise.
  1103.  */
  1104.  
  1105. BOOL CPatronDoc::FEditLinks(HWND hWndFrame)
  1106.     {
  1107.     UINT                    uRet;
  1108.     OLEUIEDITLINKS          el;
  1109.     LPCIOleUILinkContainer  pIUILinks;
  1110.  
  1111.     _fmemset(&el, 0, sizeof(el));
  1112.     el.cbStruct=sizeof(el);
  1113.     el.hWndOwner=hWndFrame;
  1114.  
  1115.     if (!m_pPG->FGetUILinkContainer(&pIUILinks))
  1116.         return FALSE;
  1117.  
  1118.     el.lpOleUILinkContainer=(LPOLEUILINKCONTAINER)pIUILinks;
  1119.     uRet=OleUIEditLinks((LPOLEUIEDITLINKS)&el);
  1120.  
  1121.     //Only the IOleUILinkContainer interface will know about dirtying.
  1122.     m_fDirty=pIUILinks->m_fDirty;
  1123.  
  1124.     el.lpOleUILinkContainer->Release();
  1125.     return TRUE;
  1126.     }
  1127.  
  1128.  
  1129.  
  1130. /*
  1131.  * CPatronDoc::FShowOrQueryObjectTypes
  1132.  *
  1133.  * Purpose:
  1134.  *  If querying, we return whether or not ShowObjects is active
  1135.  *  in this document.  Otherwise pass-through to CPages::ShowObjectTypes.
  1136.  *
  1137.  * Parameters:
  1138.  *  fShow           BOOL indicating to show the type or not.
  1139.  *
  1140.  * Return Value:
  1141.  *  None
  1142.  */
  1143.  
  1144. BOOL CPatronDoc::FShowOrQueryObjectTypes(BOOL fQuery, BOOL fShow)
  1145.     {
  1146.     if (fQuery)
  1147.         return m_fShowTypes;
  1148.  
  1149.     m_fShowTypes=fShow;
  1150.     m_pPG->ShowObjectTypes(fShow);
  1151.     return TRUE;
  1152.     }
  1153.  
  1154.  
  1155.  
  1156.  
  1157.  
  1158. /*
  1159.  * CPatronDoc::Print
  1160.  *
  1161.  * Purpose:
  1162.  *  Prints the current document.
  1163.  *
  1164.  * Parameters:
  1165.  *  hWndFrame       HWND of the frame to use for dialog parents.
  1166.  *
  1167.  * Return Value:
  1168.  *  BOOL            TRUE if printing happened, FALSE if it didn't start
  1169.  *                  or didn't complete.
  1170.  */
  1171.  
  1172. BOOL CPatronDoc::Print(HWND hWndFrame)
  1173.     {
  1174.     PRINTDLG        pd;
  1175.     BOOL            fSuccess;
  1176.  
  1177.     memset(&pd, 0, sizeof(PRINTDLG));
  1178.     pd.lStructSize=sizeof(PRINTDLG);
  1179.     pd.hwndOwner  =hWndFrame;
  1180.     pd.nCopies    =1;
  1181.     pd.nFromPage  =-1;
  1182.     pd.nToPage    =-1;
  1183.     pd.nMinPage   =1;
  1184.     pd.nMaxPage   =m_pPG->NumPagesGet();
  1185.  
  1186.     //Get the current document printer settings
  1187.     pd.hDevMode=m_pPG->DevModeGet();
  1188.  
  1189.     pd.Flags=PD_RETURNDC | PD_ALLPAGES | PD_COLLATE
  1190.         | PD_HIDEPRINTTOFILE | PD_NOSELECTION;
  1191.  
  1192.     if (!PrintDlg(&pd))
  1193.         return FALSE;
  1194.  
  1195.     //Make sure the Pages knows about any printer changes.
  1196.     if (!m_pPG->DevModeSet(pd.hDevMode, pd.hDevNames))
  1197.         {
  1198.         GlobalFree(pd.hDevMode);
  1199.         GlobalFree(pd.hDevNames);
  1200.         return FALSE;
  1201.         }
  1202.  
  1203.     //Go do the actual printing.
  1204.     fSuccess=m_pPG->Print(pd.hDC, PSZ(IDS_DOCUMENTNAME), pd.Flags
  1205.         , pd.nFromPage, pd.nToPage, pd.nCopies);
  1206.  
  1207.     if (!fSuccess)
  1208.         MessageBox(m_hWnd, PSZ(IDS_PRINTERROR), PSZ(IDS_DOCUMENTCAPTION), MB_OK);
  1209.  
  1210.     return fSuccess;
  1211.     }
  1212.  
  1213.  
  1214.  
  1215.  
  1216.  
  1217.  
  1218. /*
  1219.  * CPatronDoc::PrinterSetup
  1220.  *
  1221.  * Purpose:
  1222.  *  Selects a new printer and options for this document.
  1223.  *
  1224.  * Parameters:
  1225.  *  hWndFrame       HWND of the frame to use for dialog parents.
  1226.  *  fDefault        BOOL to avoid any dialog and just use the default.
  1227.  *
  1228.  * Return Value:
  1229.  *  UINT            Undefined
  1230.  *
  1231.  */
  1232.  
  1233. UINT CPatronDoc::PrinterSetup(HWND hWndFrame, BOOL fDefault)
  1234.     {
  1235.     PRINTDLG        pd;
  1236.  
  1237.     //Attempt to get printer metrics for the default printer.
  1238.     memset(&pd, 0, sizeof(PRINTDLG));
  1239.     pd.lStructSize=sizeof(PRINTDLG);
  1240.  
  1241.     if (fDefault)
  1242.         pd.Flags=PD_RETURNDEFAULT;
  1243.     else
  1244.         {
  1245.         pd.hwndOwner=hWndFrame;
  1246.         pd.Flags=PD_PRINTSETUP;
  1247.  
  1248.         //Get the current document printer settings
  1249.         pd.hDevMode=m_pPG->DevModeGet();
  1250.         }
  1251.  
  1252.     if (!PrintDlg(&pd))
  1253.         return FALSE;
  1254.  
  1255.     if (!m_pPG->DevModeSet(pd.hDevMode, pd.hDevNames))
  1256.         {
  1257.         GlobalFree(pd.hDevNames);
  1258.         GlobalFree(pd.hDevMode);
  1259.         return FALSE;
  1260.         }
  1261.  
  1262.     FDirtySet(TRUE);
  1263.     return 1;
  1264.     }
  1265.  
  1266.  
  1267.  
  1268.  
  1269.  
  1270.  
  1271.  
  1272. /*
  1273.  * CPatronDoc::NewPage
  1274.  *
  1275.  * Purpose:
  1276.  *  Creates a new page in the document's pages control after the
  1277.  *  current page.
  1278.  *
  1279.  * Parameters:
  1280.  *  None
  1281.  *
  1282.  * Return Value:
  1283.  *  UINT            Index of the new page.
  1284.  */
  1285.  
  1286. UINT CPatronDoc::NewPage(void)
  1287.     {
  1288.     FDirtySet(TRUE);
  1289.     return m_pPG->PageInsert(0);
  1290.     }
  1291.  
  1292.  
  1293.  
  1294.  
  1295.  
  1296.  
  1297.  
  1298. /*
  1299.  * CPatronDoc::DeletePage
  1300.  *
  1301.  * Purpose:
  1302.  *  Deletes the current page from the document.
  1303.  *
  1304.  * Parameters:
  1305.  *  None
  1306.  *
  1307.  * Return Value:
  1308.  *  UINT            Index of the now current page.
  1309.  */
  1310.  
  1311. UINT CPatronDoc::DeletePage(void)
  1312.     {
  1313.     FDirtySet(TRUE);
  1314.     return m_pPG->PageDelete(0);
  1315.     }
  1316.  
  1317.  
  1318.  
  1319.  
  1320.  
  1321.  
  1322.  
  1323. /*
  1324.  * CPatronDoc::NextPage
  1325.  *
  1326.  * Purpose:
  1327.  *  Shows the next page in the pages window.
  1328.  *
  1329.  * Parameters:
  1330.  *  None
  1331.  *
  1332.  * Return Value:
  1333.  *  UINT            Index of the new page.
  1334.  */
  1335.  
  1336. UINT CPatronDoc::NextPage(void)
  1337.     {
  1338.     UINT        iPage;
  1339.  
  1340.     iPage=m_pPG->CurPageGet();
  1341.     return m_pPG->CurPageSet(++iPage);
  1342.     }
  1343.  
  1344.  
  1345.  
  1346.  
  1347.  
  1348.  
  1349.  
  1350. /*
  1351.  * CPatronDoc::PreviousPage
  1352.  *
  1353.  * Purpose:
  1354.  *  Shows the previous page in the pages window.
  1355.  *
  1356.  * Parameters:
  1357.  *  None
  1358.  *
  1359.  * Return Value:
  1360.  *  UINT            Index of the new page.
  1361.  */
  1362.  
  1363. UINT CPatronDoc::PreviousPage(void)
  1364.     {
  1365.     UINT        iPage;
  1366.  
  1367.     //If iPage is zero, then we wrap around to the end.
  1368.     iPage=m_pPG->CurPageGet();
  1369.     return m_pPG->CurPageSet(--iPage);
  1370.     }
  1371.  
  1372.  
  1373.  
  1374.  
  1375.  
  1376.  
  1377. /*
  1378.  * CPatronDoc::FirstPage
  1379.  *
  1380.  * Purpose:
  1381.  *  Shows the first page page in the pages window.
  1382.  *
  1383.  * Parameters:
  1384.  *  None
  1385.  *
  1386.  * Return Value:
  1387.  *  UINT            Index of the new page.
  1388.  */
  1389.  
  1390. UINT CPatronDoc::FirstPage(void)
  1391.     {
  1392.     return m_pPG->CurPageSet(0);
  1393.     }
  1394.  
  1395.  
  1396.  
  1397.  
  1398.  
  1399.  
  1400. /*
  1401.  * CPatronDoc::LastPage
  1402.  *
  1403.  * Purpose:
  1404.  *  Shows the last page in the pages window.
  1405.  *
  1406.  * Parameters:
  1407.  *  None
  1408.  *
  1409.  * Return Value:
  1410.  *  UINT            Index of the last page.
  1411.  */
  1412.  
  1413. UINT CPatronDoc::LastPage(void)
  1414.     {
  1415.     return m_pPG->CurPageSet(-1);
  1416.     }
  1417.  
  1418.  
  1419.  
  1420.  
  1421.  
  1422.  
  1423. /*
  1424.  * CPatronDoc::Rename
  1425.  *
  1426.  * Purpose:
  1427.  *  Overrides the normal rename to include notification of tenants
  1428.  *  in this document of the new name.  This is so embedded objects
  1429.  *  are told the correct name through IOleObject::SetHostNames.
  1430.  *
  1431.  * Parameters:
  1432.  *  pszFile         LPSTR to the new filename.
  1433.  *
  1434.  * Return Value:
  1435.  *  None
  1436.  */
  1437.  
  1438. void CPatronDoc::Rename(LPSTR pszFile)
  1439.     {
  1440.     LPMONIKER   pmk;
  1441.  
  1442.     //We don't need to change the base class, just augment...
  1443.     CDocument::Rename(pszFile);
  1444.  
  1445.     //CHAPTER13MOD
  1446.     //Get rid of the old moniker.  The OldStd function sets the key to zero.
  1447.     if (0L!=m_dwRegROT)
  1448.         OleStdRevokeAsRunning(&m_dwRegROT);
  1449.  
  1450.     if (NULL==pszFile)
  1451.         return;
  1452.  
  1453.     CreateFileMoniker(pszFile, &pmk);
  1454.  
  1455.     if (NULL!=pmk)
  1456.         {
  1457.         OleStdRegisterAsRunning((LPUNKNOWN)this, pmk, &m_dwRegROT);
  1458.  
  1459.         //Give a moniker to linked objects in tenants.
  1460.         m_pPG->NotifyTenantsOfRename(pszFile, pmk);
  1461.  
  1462.         //No need for us to hold on to this.
  1463.         pmk->Release();
  1464.         }
  1465.     //End CHAPTER13MOD
  1466.  
  1467.     return;
  1468.     }
  1469.  
  1470.  
  1471.  
  1472.  
  1473.  
  1474. /*
  1475.  * CPatronDoc::FInsertObject
  1476.  *
  1477.  * Purpose:
  1478.  *  Retrieves a CLSID or a filename from the Insert Object dialog box
  1479.  *  and creates an object using those identifiers.
  1480.  *
  1481.  * Parameters:
  1482.  *  hWndFrame       HWND of the main window
  1483.  *
  1484.  * Return Value:
  1485.  *  BOOL            TRUE if successful, FALSE otherwise.
  1486.  */
  1487.  
  1488. BOOL CPatronDoc::FInsertObject(HWND hWndFrame)
  1489.     {
  1490.     OLEUIINSERTOBJECT   io;
  1491.     DWORD               dwData=0;
  1492.     char                szFile[CCHPATHMAX];
  1493.     UINT                uTemp;
  1494.     BOOL                fRet=FALSE;
  1495.  
  1496.     if (NULL==m_pPG)
  1497.         return FALSE;
  1498.  
  1499.     _fmemset(&io, 0, sizeof(io));
  1500.  
  1501.     io.cbStruct=sizeof(io);
  1502.     io.hWndOwner=hWndFrame;
  1503.  
  1504.     szFile[0]=0;
  1505.     io.lpszFile=szFile;
  1506.     io.cchFile=sizeof(szFile);
  1507.     io.dwFlags=IOF_SELECTCREATENEW;
  1508.  
  1509.     uTemp=OleUIInsertObject(&io);
  1510.  
  1511.     if (OLEUI_OK==uTemp)
  1512.         {
  1513.         TENANTTYPE      tType;
  1514.         LPVOID          pv;
  1515.         FORMATETC       fe;
  1516.  
  1517.         SETDefFormatEtc(fe, 0, TYMED_NULL);
  1518.  
  1519.         if (io.dwFlags & IOF_SELECTCREATENEW)
  1520.             {
  1521.             tType=TENANTTYPE_EMBEDDEDOBJECT;
  1522.             pv=(LPVOID)&io.clsid;
  1523.             }
  1524.         else
  1525.             {
  1526.             if (io.dwFlags & IOF_CHECKLINK)
  1527.                 tType=TENANTTYPE_LINKEDFILE;
  1528.             else
  1529.                 tType=TENANTTYPE_EMBEDDEDFILE;
  1530.  
  1531.             pv=(LPVOID)szFile;
  1532.             }
  1533.  
  1534.         if ((io.dwFlags & IOF_CHECKDISPLAYASICON) && NULL!=io.hMetaPict)
  1535.             {
  1536.             fe.dwAspect=DVASPECT_ICON;
  1537.             dwData=(DWORD)(UINT)io.hMetaPict;
  1538.             }
  1539.  
  1540.         fRet=m_pPG->TenantCreate(tType, pv, &fe, NULL, dwData);
  1541.  
  1542.         //Free this regardless of what we do with it.
  1543.         if (NULL!=io.hMetaPict)
  1544.             OleUIMetafilePictIconFree(io.hMetaPict);
  1545.  
  1546.         if (fRet)
  1547.             {
  1548.             //Disable Printer Setup once we've created a tenant.
  1549.             m_fPrintSetup=FALSE;
  1550.             FDirtySet(TRUE);
  1551.             }
  1552.         }
  1553.  
  1554.     return fRet;
  1555.     }
  1556.  
  1557.  
  1558.  
  1559.  
  1560. /*
  1561.  * CPatronDoc::ActivateObject
  1562.  *
  1563.  * Purpose:
  1564.  *  Executes a verb on the currently selected object.
  1565.  *
  1566.  * Parameters:
  1567.  *  iVerb           UINT of the selected verb.
  1568.  *
  1569.  * Return Value:
  1570.  *  None
  1571.  */
  1572.  
  1573. void CPatronDoc::ActivateObject(UINT iVerb)
  1574.     {
  1575.     m_pPG->ActivateObject(iVerb);
  1576.     return;
  1577.     }
  1578.